package org.example.domain.strategy.service.rule.tree.factory.engine.impl;

import lombok.extern.slf4j.Slf4j;
import org.example.domain.strategy.model.vo.RuleLogicCheckTypeVO;
import org.example.domain.strategy.model.vo.RuleTreeNodeLineVO;
import org.example.domain.strategy.model.vo.RuleTreeNodeVO;
import org.example.domain.strategy.model.vo.RuleTreeVO;
import org.example.domain.strategy.service.rule.tree.ILogicTreeNode;
import org.example.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
import org.example.domain.strategy.service.rule.tree.factory.engine.IDecisionTreeEngine;

import java.util.Date;
import java.util.List;
import java.util.Map;


/**
 * 决策树引擎
 */
@Slf4j
public class DecisionTreeEngine implements IDecisionTreeEngine {

    private final Map<String , ILogicTreeNode> logicTreeNodeGroup;

    private final RuleTreeVO ruleTreeVO;

    public DecisionTreeEngine(Map<String, ILogicTreeNode> logicTreeNodeGroup, RuleTreeVO ruleTreeVO) {
        this.logicTreeNodeGroup = logicTreeNodeGroup;
        this.ruleTreeVO = ruleTreeVO;
    }


    @Override
    public DefaultTreeFactory.StrategyAwardVO process(String userId, Long StrategyId, Integer awardId,Date endDateTime) {

        DefaultTreeFactory.StrategyAwardVO strategyAwardData = null;

        //获取基础信息
        String nextNode = ruleTreeVO.getTreeRootRuleNode();
        Map<String, RuleTreeNodeVO> treeNodeMap = ruleTreeVO.getTreeNodeMap();

        //获取起始结点【根节点记录了第一个要执行的规则】---- 虚拟的规则结点，只是一个装载了结点信息的结点，没有实现具体逻辑的方法
        RuleTreeNodeVO ruleTreeNode = treeNodeMap.get(nextNode);
        while (null != nextNode){
            //获取决策结点-----实际的规则结点，有实现具体逻辑的方法
            ILogicTreeNode logicTreeNode = logicTreeNodeGroup.get(ruleTreeNode.getRuleKey());
            String ruleValue = ruleTreeNode.getRuleValue();


            //决策点计算
            DefaultTreeFactory.TreeActionEntity logicEntity = logicTreeNode.logic(userId, StrategyId, awardId,ruleValue,endDateTime);
            RuleLogicCheckTypeVO ruleLogicCheckTypeVO = logicEntity.getRuleLogicCheckType();
            strategyAwardData = logicEntity.getStrategyAwardData();
            log.info("决策树引擎【{}】 treeId:{} node:{} code:{}",ruleTreeVO.getTreeName(),ruleTreeVO.getTreeId(),nextNode,ruleLogicCheckTypeVO.getCode());


            //获取下一个结点
            nextNode = nextNode(ruleLogicCheckTypeVO.getCode(),ruleTreeNode.getTreeNodeLineVOList());

            ruleTreeNode = treeNodeMap.get(nextNode);
        }


        return strategyAwardData;
    }

    /**
     *
     * @param matterValue  规则树结点指向线的限制值【是“接管”，就走限制值是“接管”的那条线】
     * @param treeNodeLineVOList 存放 该节点的指向线 的列表
     * @return
     */
    public String nextNode(String matterValue, List<RuleTreeNodeLineVO> treeNodeLineVOList){


        if(null == treeNodeLineVOList || treeNodeLineVOList.isEmpty()){
            return null;
        }

        //根据限制值matterValue去匹配指向线
        for(RuleTreeNodeLineVO nodeLine : treeNodeLineVOList){
            if(descisionLogic(matterValue,nodeLine)){
                return nodeLine.getRuleNodeTo();
            }
        }

        //throw new RuntimeException("决策树引擎，nextNode计算失败，未找到可执行结点！");
        return null;

    }

    /**
     * 判断限制值matterValue是否和该指向线的限制值相等
     * @param matterValue
     * @param nodeLine
     * @return
     */
    public boolean descisionLogic(String matterValue,RuleTreeNodeLineVO nodeLine){
        switch (nodeLine.getRuleLimitType()){
            case EQUAL:  return matterValue.equals(nodeLine.getRuleLimitValue().getCode());
            //以下规则暂时不需要实现
            case GT:
            case LT:
            case GE:
            case LE:
            case ENUM:
            default: return false;
        }
    }
}
